package org.anderground.app.activity;

import org.anderground.app.AndergroundApp;
import org.anderground.app.R;
import org.anderground.app.activity.StateStack.State;
import org.anderground.core.model.Line;
import org.anderground.core.model.Station;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.Drawable;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * @author Eldar Abusalimov
 */
public class StationInfoState extends State {

	/** Lazily inflated popup View instance */
	private static View popupView;

	private static TextView nameText;
	private static ImageView iconImage;
	private static TextView scheduleText;

	/** view group to attach popup view to */
	private ViewGroup viewGroup;

	private LayoutParams layoutParams;

	private Station station;

	/**
	 * @param application
	 */
	public StationInfoState(AndergroundApp app, ViewGroup viewGroup,
			LayoutParams layoutParams, Station station) {
		super(app);
		this.viewGroup = viewGroup;
		this.layoutParams = layoutParams;
		this.station = station;
	}

	@Override
	public boolean enterFrom(State state) {
		if (popupView == null) {
			View view = LayoutInflater.from(getApp()).inflate(
					R.layout.station_popup, null);
			popupView = view;
			nameText = (TextView) view.findViewById(R.id.name);
			iconImage = (ImageView) view.findViewById(R.id.icon);
			scheduleText = (TextView) view.findViewById(R.id.schedule);
		}

		ViewParent parent = popupView.getParent();
		if (parent != null && parent instanceof ViewGroup) {
			ViewGroup oldGroup = (ViewGroup) parent;
			oldGroup.removeView(popupView);
		}

		nameText.setText(station.getName());
		iconImage.setImageDrawable(new StationDrawable(station));
		scheduleText.setText("");
		scheduleText.append(getApp().getText(R.string.station_open));
		scheduleText.append(station.getOpenTime().toString());
		scheduleText.append("   ");
		scheduleText.append(getApp().getText(R.string.station_close));
		scheduleText.append(station.getCloseTime().toString());

		viewGroup.addView(popupView, layoutParams);

		return true;
	}

	@Override
	public void exit() {
		ViewParent parent = popupView.getParent();
		if (parent == viewGroup) {
			ViewGroup oldGroup = (ViewGroup) parent;
			oldGroup.removeView(popupView);
		}
	}

	/**
	 * Simple {@link Station} icon.
	 * 
	 * @author Eldar Abusalimov
	 */
	public static class StationDrawable extends Drawable {

		private static final int STATION_RADIUS = 10;
		private static final int LINE_WIDTH = 10;
		private static final int SHADOW_RADIUS = 2;

		private static Paint linePaint;
		private Paint stationPaint;

		private SparseIntArray colors = new SparseIntArray();

		private int width, height;

		/**
		 * 
		 * @param station
		 */
		public StationDrawable(Station station) {
			stationPaint = new Paint();
			stationPaint.setAntiAlias(true);
			stationPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, Color.GRAY);

			Line[] lines = station.getLines();
			if (lines.length == 1) {
				int color = lines[0].getColor();
				stationPaint.setColor(color);
				colors.put(0, color);
			} else {
				int startOffset = -(lines.length - 1) * LINE_WIDTH / 2;
				for (int i = 0; i < lines.length; i++) {
					colors.put(startOffset + i * LINE_WIDTH, lines[i]
							.getColor());
				}
				stationPaint.setColor(Color.LTGRAY);
			}
		}

		@Override
		public void draw(Canvas canvas) {
			final int centerX = width / 2;
			final int centerY = height / 2;
			final float padding = LINE_WIDTH / 2f + SHADOW_RADIUS;

			linePaint.setAlpha(stationPaint.getAlpha());
			for (int i = 0; i < colors.size(); i++) {
				int lineY = centerY + colors.keyAt(i);
				linePaint.setColor(colors.valueAt(i));
				canvas.drawLine(padding, lineY, width - padding, lineY,
						linePaint);
			}

			canvas.drawCircle(centerX, centerY, STATION_RADIUS, stationPaint);
		}

		@Override
		protected void onBoundsChange(Rect bounds) {
			width = bounds.width();
			height = bounds.height();
			stationPaint.setShader(new RadialGradient(width / 2f + 1,
					height / 2f + 1, STATION_RADIUS + 2, Color.WHITE,
					stationPaint.getColor(), TileMode.MIRROR));
			super.onBoundsChange(bounds);
		}

		@Override
		public int getOpacity() {
			return PixelFormat.TRANSLUCENT;
		}

		@Override
		public void setAlpha(int alpha) {
			stationPaint.setAlpha(alpha);
		}

		@Override
		public void setColorFilter(ColorFilter cf) {
		}

		@Override
		public int getMinimumWidth() {
			return (STATION_RADIUS + LINE_WIDTH + SHADOW_RADIUS) * 2;
		}

		@Override
		public int getMinimumHeight() {
			return Math.max(STATION_RADIUS * 2, LINE_WIDTH * colors.size())
					+ SHADOW_RADIUS * 2;
		}

		@Override
		public int getIntrinsicWidth() {
			return getMinimumWidth();
		}

		@Override
		public int getIntrinsicHeight() {
			return getMinimumHeight();
		}

		static {
			linePaint = new Paint();
			linePaint.setAntiAlias(true);
			linePaint.setStrokeCap(Paint.Cap.ROUND);
			linePaint.setStrokeWidth(LINE_WIDTH);
			linePaint.setShadowLayer(SHADOW_RADIUS, 0, 0, Color.GRAY);
		}

	}

}
